﻿///////////////////////////////////////////////////////////////////////////////
///
/// Cylan Client Core
/// Copyright (C) Shenzhen Cylan Tech. Co., Ltd. 2012
///
/// @file       Session.h
/// @brief      会话管理API
///
///////////////////////////////////////////////////////////////////////////////
#ifndef CYLAN_SESSION_H
#define CYLAN_SESSION_H

/**
 * @struct CSESSION_LOGIN_SERVER
 * @brief  登录服务器参数类型
 */
typedef struct CSESSION_LOGIN_SERVER
{
    char Address[CC_MAX_URL];                   ///< 服务器地址[:端口]
    int  Protocol;                              ///< 服务器协议(当前忽略)
} CSESSION_LOGIN_SERVER;


/**
 * @struct CSESSION_LOGIN_TOKEN_FLAGS
 * @brief  令牌参数有效属性
 */
typedef enum CSESSION_LOGIN_TOKEN_FLAGS
{
    SessionLoginTokenFlagUserPass = 1 << 1,     ///< 使用用户名密码登录
    SessionLoginTokenFlagCertificate = 1 << 2,  ///< 使用证书登录
    SessionLoginTokenFlagSMSVerify = 1 << 3,    ///< 提供短讯认证码
    SessionLoginTokenFlagDynamicPwd = 1 << 4,   ///< 提供动态口令
    SessionLoginTokenFlagReuseSession = 1 << 5, ///< 使用已有的会话, 将会忽略其他登录方式
    SessionLoginTokenFlagExLocalPass = 1 << 6,  ///< 提供二次私人口令
    SessionLoginTokenFlagServerId = 1 << 7,     ///< 使用ServerId参数
    SessionLoginTokenFlagReserve = 1 << 8       ///< 使用Reserve参数
} CSESSION_LOGIN_TOKEN_FLAGS;


/**
 * @enum CSESSION_LOGIN_CLIENT_TYPE
 * @brief  登录客户端设备类型
 */
typedef enum CSESSION_LOGIN_CLIENT_TYPE
{
    SessionLoginClientTypeDesktop = 0,          ///< 桌面版
    SessionLoginClientTypeAndroidPhone = 1,     ///< Android Phone 客户端
    SessionLoginClientTypeAndroidPad = 2,       ///< Android Pad 客户端
    SessionLoginClientTypeIPhone = 3,           ///< iPhone 客户端
    SessionLoginClientTypeIPad = 4,             ///< iPad 客户端
    SessionLoginClientTypeIBox = 5,             ///< iBox 客户端
    SessionLoginClientTypeUnserver = 6          ///< 统一认证服务器
} CSESSION_LOGIN_CLIENT_TYPE;



/**
 * @struct CSESSION_LOGIN_TOKEN
 * @brief  令牌参数有效属性
 */
typedef struct CSESSION_LOGIN_TOKEN
{
    unsigned int    TokenSize;                  ///< 令牌参数大小
    unsigned int    Flags;                      ///< 令牌参数有效属性, 参考 CSESSION_LOGIN_TOKEN_FLAGS
    CSESSION_LOGIN_CLIENT_TYPE ClientType;      ///< 客户端类型
    const char *    MagicNull;                  ///< 必须设为NULL
    const char *    Username;                   ///< 账号
    const char *    Password;                   ///< 密码
    const char *    CertFile;                   ///< 证书文件路径
    const char *    PINCode;                    ///< 证书PIN码
    const char *    PackageName;                ///< 登录客户端包名字
    const char *    SMSCode;                    ///< 短讯认证码
    const char *    ClientVersion;              ///< 客户端版本号, x.x.x,x为数字
    const char *    HardwareId;                 ///< 硬件ID(移动设备)
    const char *    DynamicPwd;                 ///< 动态口令
    const char *    ExLoaclPwd;                 ///< 二次校验口令    
    const char *    SessionId;                  ///< 使用已有的会话
    const char *    ISPCode;                    ///< 运营商编码
    const char *    NETWORKTYPE;                ///< wifi 或者 非wifi(3G)
    const char *    MCC;                        ///< 移动设备国家代码
    const char *    SIMID;                      ///< SIM卡 ID
    int             ServerId;                   ///< 统一认证服务器Id
    const char *    Reserve;                    ///< SGA扩展参数
} CSESSION_LOGIN_TOKEN;


/**
 * @enum CSESSION_INFO_CLASS
 * @brief 可供查询的会话信息
 */
typedef enum CSESSION_INFO_CLASS
{
    SessionInfoSessionID,                       ///< char: 会话ID
    SessionInfoVersionSGA,                      ///< int:  SGA版本
    SessionInfoVersionAndroidPad,               ///< int:  AndroidPad版本
    SessionInfoVersionAndroidPhone,             ///< int:  AndroidPhone版本
    SessionInfoVersionIPhone,                   ///< int:  iPhone最新客户端版本
    SessionInfoVersionIPad,                     ///< int:  iPad最新客户端版本
    SessionInfoVersionPC,                       ///< int:  PC客户端最新版本
    SessionInfoUpgradeMode,                     ///< int:  客户端升级模式    
    SessionInfoUpgradeTip,                      ///< int:  客户端版本升级说明
    SessionInfoUpgradeWebUrl,                   ///< int:  web升级地址
    SessionInfoUpgradeAndroidPadUrl,            ///< int:  android phone升级地址
    SessionInfoUpgradeAndroidPhoneUrl,          ///< int:  android pad升级地址
    SessionInfoUpgradePCUrl,                    ///< int:  PC客户端 升级提示
    SessionInfoUpgradeiPhonePlist,              ///< int:  iphone plist  
    SessionInfoUpgradeiPadPlist,                ///< int:  ipad plist
    SessionInfoUpgradeForce,                    ///< int:  是否要求客户端强制升级       
    SessionInfoUserName,                        ///< char: 用户名
    SessionInfoUserIBOXShareAll,                ///< int:  IBOX共享给所有人权限
    SessionInfoServerID,                        ///< char: SGA的唯一标识
    SessionInfoServerEnableIBOX,                ///< int:  是否启用IBOX功能
    SessionInfoServerForbidIBOXUpload,          ///< int:  是否禁止IBOX上传功能
    SessionInfoServerForbidIBOXDownload,        ///< int:  是否禁止IBOX下载功能
    SessionInfoServerUseHttp,                   ///< int:  是否启用HTTP在线打开
    SessionInfoServerHttpPort,                  ///< int:  是否启用IBOX功能
    SessionInfoServerEnableLossyCompress,       ///< int:  是否启用有损压缩
    SessionInfoServerIconCreateTime,            ///< int:  图标更新时间
    SessionInfoServerMaxIdleTime,               ///< int:  会话超时时间
    SessionInfoServerIBOXHostName,              ///< char: IBOX专用服务器
    SessionInfoServerRedirectUri,               ///< char: SGA返回的重定向Uri
    SessionInfoLoginErrorMessage,               ///< char: 登陆返回的错误描述信息
    SessionInfoEnableSingleResource,            ///< int:  单个资源是否自动登陆
    SessionInfoNeedChangePassForce,				///< int:  是否要求客户端强制改密码
    SessionInfoServerGroupIBOX,                 ///< int:  IBOX组共享
	SessionInfoUserType,                        ///< int:  公有用户或私有用户
    SessionInfoEnableCacheClean,                ///< int:  是否清除缓存
    SessionInfoEnableScreenCapture              ///< int:  是否允许截屏
} CSESSION_INFO_CLASS;


/**
 * @fn CHANDLE CSessionNew()
 * @brief 创建一个Session对象, 用于建立和管理客户端到服务器的通讯
 * @return Session句柄
 */
CHANDLE CSessionNew();

/**
 * @fn SGA_ERROR_CODE CSessionSGAError(CHANDLE Session)
 * @brief 获取上一次服务器请求的SGA错误码
 */
SGA_ERROR_CODE CSessionSGAError(CHANDLE Session);


/**
 * @fn CC_STATUS CSessionLogin(CHANDLE Session, const CSESSION_LOGIN_SERVER * const Server, const CSESSION_LOGIN_TOKEN * const Token)
 * @brief 建立一个客户端到服务器的会话.
 * @param Session Session句柄
 * @param Server 服务器地址
 * @param Token 用户令牌
 * @retval ERR_SUCCESS 登录成功
 * @retval ERR_SGACALL SGA错误, 使用CSessionSGAError函数获取进一步信息
 * @retval ERR_LOGIN_CERT_FILE 证书登陆证书文件错误
 * @retval ERR_LOGIN_CERT_PIN 证书登陆PIN码错误
 * @retval ERR_INVALID_PARAMETER 参数错误
 * @note Token的TokenSize设置不正确会返回ERR_INVALID_PARAMETER
 * @note 使用Server和Token结构体之前, 应先以0x00填充
 */
CC_STATUS CSessionLogin(CHANDLE Session,
                        const CSESSION_LOGIN_SERVER* const Server,
                        const CSESSION_LOGIN_TOKEN* const Token);


/**
 * @fn CC_STATUS CSessionRefresh(CHANDLE Session)
 * @brief 刷新已登录会话, 从服务器重新获取资源数据
 * @param Session Session句柄
 * @retval ERR_SUCCESS 登录成功
 * @retval ERR_SGACALL SGA错误, 使用CSessionSGAError函数获取进一步信息
 */
CC_STATUS CSessionRefresh(CHANDLE Session);

/**
 * @fn CC_STATUS CSessionSendSMS(CHANDLE Session)
 * @brief 发送短讯认证码
 * @param Session Session句柄
 */
CC_STATUS CSessionSendSMS(CHANDLE Session);


/**
 * @fn CC_STATUS CSessionSendHeartbeat(CHANDLE Session)
 * @brief 发送保活心跳
 * @param Session Session句柄
 * @retval ERR_SUCCESS 操作成功
 * @retval ERR_SGACALL 操作失败, SGA错误, 调用CSessionSGAError()获取错误信息
 * @see CSessionSGAError
 */
CC_STATUS CSessionSendHeartbeat(CHANDLE Session);


/**
 * @fn CC_STATUS CSessionChangePassword(CHANDLE Session, const char *OldPassword, const char *NewPassword)
 * @brief 修改用户密码
 * @param Session Session句柄
 * @param OldPassword 原密码
 * @param NewPassword 新密码
 * @retval ERR_SUCCESS 操作成功
 * @retval ERR_SGACALL 操作失败, SGA错误, 调用CSessionSGAError()获取错误信息
 * @see CSessionSGAError
 */
CC_STATUS CSessionChangePassword(CHANDLE Session, const char *OldPassword, const char *NewPassword);



/**
* @fn CC_STATUS CSessionQuery(CHANDLE Session, CSESSION_INFO_CLASS InfoClass, void *Buffer, int *Size)
 * @brief 查询会话信息
 * @param Session 会话句柄
 * @param InfoClass 会话信息类型
 * @param Buffer 用以保存返回结果的缓冲区
 * @param Size 缓冲区大小
 * @return ERR_SUCCESS 查询成功
 * @return ERR_NOT_FOUND 无此配置
 * @return ERR_BUFFER_TOO_SMALL 所需缓冲区大小不足
 * @code
 * //
 * // Example:
 * //
 * // 查询会话用户名, 获取字符串结果要使用 char **,
 * // InfoString不需要分配内存和释放, 不可更改其返回的内容, 否则会产生不可预料的后果
 * int   InfoSize   = sizeof(char *);
 * char *InfoString = NULL;
 * CC_STATUS Result = CSessionQuery(Session, SessionInfoUserName, &InfoString, &InfoSize);
 *
 * // 查询SGA版本
 * int   InfoSize   = sizeof(int);
 * int   InfoNumber = 0;
 * CC_STATUS Result = CSessionQuery(Session, SessionInfoVersionSGA, &InfoNumber, &InfoSize);
 *
 * @endcode
 */
CC_STATUS CSessionQuery(CHANDLE Session,
                        CSESSION_INFO_CLASS InfoClass,
                        void *Buffer,
                        int *Size);


/**
 * @fn CC_STATUS CSessionLogout(CHANDLE Session)
 * @brief 注销用户会话
 * @param Session Session句柄
 * @retval ERR_SUCCESS 登出成功
 */
CC_STATUS CSessionLogout(CHANDLE Session);



/**
 * @fn CC_STATUS CSessionUnserialize(CHANDLE Session, const CSESSION_LOGIN_SERVER * const Server, const char * const SessionId, const char * const SessionFile)
 * @brief 从一个序列化的Session文件中恢复会话对象
 * @param[in] Session 新建的Session句柄
 * @param[in] Server 服务器地址
 * @param[in] SessionId 会话ID
 * @param[in] SessionFile 会话文件
 * @retval ERR_SUCCESS 登录成功
 * @retval ERR_INVALID_PARAMETER SessionFile文件无效
 */
CC_STATUS CSessionUnserialize(CHANDLE Session, 
                              const CSESSION_LOGIN_SERVER * const Server, 
                              const char * const SessionId,
                              const char * const SessionFile);

/**
 * @fn CC_STATUS CSessionLogoutForAndroid(CHANDLE Session)
 * @brief 注销用户会话
 * @param Session Session句柄
 * @retval ERR_SUCCESS 登出成功
 */
CC_STATUS CSessionLogoutForAndroid(CHANDLE Session);


/**
 * @fn CC_STATUS CSessionGetServerUrl(CHANDLE Session, char *ServerUrl, int *Size)
 * @brief 返回ServerUrl地址
 * @param Session Session句柄
 * @param ServerUrl 调用者提供的缓冲区以保存ServerUrl地址
 * @param Size ServerUrl参数的缓冲区大小. 如果提供的缓冲区太小, 会返回所需的缓冲区大小字节数.
 * @retval ERR_SUCCESS 成功
 * @retval ERR_BUFFER_TOO_SMALL 提供的pSsoSettingUrl缓冲区太小
 */
CC_STATUS CSessionGetServerUrl(CHANDLE Session, char *ServerUrl, int *Size);

/**
 * @fn CC_STATUS CSessionQueryServerByCompanyName(char *Domain, char *Company, CSESSION_LOGIN_SERVER *Server)
 * @brief 根据企业ID查询SGA服务器
 * @param Domain 登录服务器地址
 * @param Company 注册企业客户名称
 * @param Server 返回域名:端口字符串
 * @retval ERR_SUCCESS 成功
*/
CC_STATUS CSessionQueryServerByCompanyName(char *Domain, char *Company, CSESSION_LOGIN_SERVER *Server);

#endif /* CYLAN_SESSION_H */
